package war2100;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

import war2100.editor.EntityChoice;
import war2100.editor.MapDisplay;
import war2100.editor.OpenFilter;
import war2100.editor.TileChoice;
import war2100.editor.menu.handler.ExitHandler;
import war2100.editor.menu.handler.MapHandler;
import war2100.editor.menu.handler.NewHandler;
import war2100.editor.menu.handler.OpenHandler;
import war2100.editor.menu.handler.SaveHandler;
import war2100.entity.Map;
import war2100.entity.SerializableMap;
import war2100.entity.tiles.Tile;

public class Editor extends JFrame {
	private static final long serialVersionUID = 2545081866962663972L;

	private JMenuItem saveMenuItem;
	private JMenuItem newColumnItem;
	private JMenuItem newLineItem;
	private JMenuItem removeLineItem;
	private JMenuItem removeColumnItem;

	private boolean mapIsModified;
	private MapDisplay mapDisplay;
	private TileChoice tileChoice;
	private EntityChoice entityChoice;
	private Map map;
	private Object currentSetObject;
	private Tile currentTile;
	private Prototypes prototypes;

	public Editor() {
		this.mapIsModified = false;
		prototypes = new Prototypes(Prototypes.TYPE_EDITOR);

		JMenuBar menuBar = new JMenuBar();

		JMenu fileMenu = new JMenu("Datei");
		menuBar.add(fileMenu);
		JMenuItem newMenuItem = new JMenuItem("Neu");
		newMenuItem.addActionListener(new NewHandler(this));
		fileMenu.add(newMenuItem);
		saveMenuItem = new JMenuItem("Speichern");
		saveMenuItem.addActionListener(new SaveHandler(this));
		fileMenu.add(saveMenuItem);
		saveMenuItem.setEnabled(false);
		JMenuItem openMenuItem = new JMenuItem("\u00D6ffnen");
		openMenuItem.addActionListener(new OpenHandler(this));
		fileMenu.add(openMenuItem);
		JMenuItem exitMenuItem = new JMenuItem("Beenden");
		exitMenuItem.addActionListener(new ExitHandler());
		fileMenu.add(exitMenuItem);

		JMenu mapMenu = new JMenu("Map");
		menuBar.add(mapMenu);
		newColumnItem = new JMenuItem("Spalte hinzufügen");
		newColumnItem.setEnabled(false);
		newColumnItem.addActionListener(new MapHandler(this, MapHandler.TYPE_ADDCOLUMN));
		mapMenu.add(newColumnItem);

		newLineItem = new JMenuItem("Zeile hinzufügen");
		newLineItem.setEnabled(false);
		newLineItem.addActionListener(new MapHandler(this, MapHandler.TYPE_ADDLINE));
		mapMenu.add(newLineItem);

		removeColumnItem = new JMenuItem("Spalte entfernen");
		removeColumnItem.setEnabled(false);
		removeColumnItem.addActionListener(new MapHandler(this, MapHandler.TYPE_REMOVECOLUMN));
		mapMenu.add(removeColumnItem);

		removeLineItem = new JMenuItem("Zeile entfernen");
		removeLineItem.setEnabled(false);
		removeLineItem.addActionListener(new MapHandler(this, MapHandler.TYPE_REMOVELINE));
		mapMenu.add(removeLineItem);

		this.setJMenuBar(menuBar);

		JPanel choicePanel = new JPanel();
		choicePanel.setLayout(new GridLayout(0, 1));
		tileChoice = new TileChoice(this);
		choicePanel.add(tileChoice);
		entityChoice = new EntityChoice(this);
		choicePanel.add(entityChoice);

		mapDisplay = new MapDisplay(this);
		JScrollPane scrollPane = new JScrollPane(getMapDisplay());

		this.add(scrollPane, BorderLayout.CENTER);

		// this.add(mapDisplay);
		this.add(choicePanel);

		Dimension screensize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
		setLayout(new GridLayout(1, 0));
		setSize(640, 480);
		setLocation((int) (screensize.getWidth() / 4) - (this.getWidth() / 2), (int) (screensize.getHeight() / 4) - (this.getHeight() / 2));
		setVisible(true);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

	}

	public void newWorld() {
		String width = JOptionPane.showInputDialog(null, "Bitte die Breite der neuen Welt eingeben : ", "Neue Welt erstellen - Breite", 1);
		if (width != null) {
			String height = JOptionPane.showInputDialog(null, "Bitte die Höhe der neuen Welt eingeben : ", "Neue Welt erstellen - Höhe", 1);
			if (height != null) {
				if (width.matches("[+-]?[0-9]+") && height.matches("[+-]?[0-9]+")) {
					map = new Map(Integer.parseInt(width), Integer.parseInt(height), currentTile);
					getMapDisplay().setMap(map);
					repaint();

					saveMenuItem.setEnabled(true);
					newColumnItem.setEnabled(true);
					newLineItem.setEnabled(true);
					removeLineItem.setEnabled(true);
					removeColumnItem.setEnabled(true);
				}
			}
		}
	}

	public void saveWorld() throws IOException {

		JFileChooser fc = new JFileChooser();

		final File defaultPath = new File("./map");
		fc.setCurrentDirectory(defaultPath);

		fc.setFileFilter(new OpenFilter(".map"));
		fc.setAcceptAllFileFilterUsed(false);
		int state = fc.showSaveDialog(null);

		if (state == 0) {
			File file = fc.getSelectedFile();
			if (file.getName().indexOf(".") == -1)
				file = new File(file.getAbsolutePath() + ".map");
			try {
				file.createNewFile();
			}
			catch (IOException e) {
				e.printStackTrace();
			}

			try {
				ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(file));
				os.writeObject(new SerializableMap(map));
				os.close();
			}
			catch (IOException e1) {
				e1.printStackTrace();
			}
		}

	}

	public boolean openWorld() throws IOException {

		JFileChooser fc = new JFileChooser();

		final File defaultPath = new File("./map");
		fc.setCurrentDirectory(defaultPath);

		fc.setFileFilter(new OpenFilter(".map"));
		fc.setAcceptAllFileFilterUsed(false);
		int state = fc.showOpenDialog(null);

		if (state == 0) {
			File file = fc.getSelectedFile();

			ObjectInputStream is;
			try {
				is = new ObjectInputStream(new FileInputStream(file));
				SerializableMap sMap = (SerializableMap) is.readObject();
				Map map = sMap.getMap(this);
				getMapDisplay().setMap(map);
				this.map = map;
				is.close();
				repaint();
				saveMenuItem.setEnabled(true);
				newColumnItem.setEnabled(true);
				newLineItem.setEnabled(true);
				removeLineItem.setEnabled(true);
				removeColumnItem.setEnabled(true);

				return true;
			}
			catch (FileNotFoundException e1) {
				e1.printStackTrace();
				return false;
			}
			catch (IOException e1) {
				JOptionPane.showMessageDialog(null, "Die Datei ist ungültig und konnte nicht geöffnet werden.", "Ungültige Datei", JOptionPane.ERROR_MESSAGE);
				return false;
			}
			catch (ClassNotFoundException e) {
				e.printStackTrace();
				return false;
			}
		}

		return false;
	}

	public static void main(String[] args) {

		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		}
		catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		catch (InstantiationException e) {
			e.printStackTrace();
		}
		catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		catch (UnsupportedLookAndFeelException e) {
			e.printStackTrace();
		}
		new Editor();
	}

	public boolean isMapIsModified() {
		return mapIsModified;
	}

	public Map getMap() {
		return map;
	}

	public void setMap(Map map) {
		this.map = map;
	}

	public TileChoice getTileChoice() {
		return tileChoice;
	}

	public void setTileChoice(TileChoice tileChoice) {
		this.tileChoice = tileChoice;
	}

	public Object getCurrentSetObject() {
		return currentSetObject;
	}

	public void setCurrentSetObject(Object currentSetObject) {
		this.currentSetObject = currentSetObject;
		if (currentSetObject instanceof Tile) {
			this.currentTile = (Tile) currentSetObject;
		}
	}

	public Tile getCurrentTile() {
		return currentTile;
	}

	public void setCurrentTile(Tile currentTile) {
		this.currentTile = currentTile;
	}

	public Prototypes getPrototypes() {
		return prototypes;
	}

	public void setPrototypes(Prototypes prototypes) {
		this.prototypes = prototypes;
	}

	/**
	 * @return the mapDisplay
	 */
	public MapDisplay getMapDisplay() {
		return mapDisplay;
	}

	/**
	 * @param mapDisplay
	 *            the mapDisplay to set
	 */
	public void setMapDisplay(MapDisplay mapDisplay) {
		this.mapDisplay = mapDisplay;
	}

	/**
	 * @param mapIsModified
	 *            the mapIsModified to set
	 */
	public void setMapIsModified(boolean mapIsModified) {
		this.mapIsModified = mapIsModified;
	}

}
